package com.lhkj.ct.meta.modules.psychology.service;

import com.lhkj.ct.base.constants.Constants;
import com.lhkj.ct.base.model.Option;
import com.lhkj.ct.base.utils.image.ImageUtils;
import com.lhkj.ct.base.utils.file.excel.ExcelUtils;
import com.lhkj.ct.meta.admin.service.SysDictDataService;
import com.lhkj.ct.meta.modules.common.enums.PatientModule;
import com.lhkj.ct.meta.modules.gauge.common.enums.QuestionType;
import com.lhkj.ct.meta.modules.gauge.model.entity.TblGaugeOption;
import com.lhkj.ct.meta.modules.gauge.model.entity.TblGaugeQuestion;
import com.lhkj.ct.meta.modules.psychology.model.bo.PatientItem;
import com.lhkj.ct.meta.modules.psychology.model.bo.PsyExportParam;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.Units;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 描述
 * </p>
 *
 * @author job
 * @since 2023/10/23
 */
@Service
public class PsyExportProcess {

    private final Logger logger = LoggerFactory.getLogger(PsyExportProcess.class);

    @Resource
    private SysDictDataService dictDataService;

    private static final int gaugeExcelMaxCol = 8;

    public Workbook generateExcel(PsyExportParam data) {
        // 初始化工作表
        XSSFWorkbook workbook = new SXSSFWorkbook().getXSSFWorkbook();
        // 创建工作簿
        Sheet sheet = workbook.createSheet("Sheet");
        // tips 取消默认边框
        sheet.setDisplayGridlines(false);
        // 设置工作表密码
        sheet.protectSheet("password");
        // 设置默认列宽
        sheet.setDefaultColumnWidth(13);
        // 边框 + 锁
        CellStyle border_locked_style = workbook.createCellStyle();
        border_locked_style.setBorderTop(BorderStyle.THIN);// 上边框
        border_locked_style.setBorderRight(BorderStyle.THIN);// 右边框
        border_locked_style.setBorderBottom(BorderStyle.THIN); // 下边框
        border_locked_style.setBorderLeft(BorderStyle.THIN);// 左边框

        // 边框样式 + 无锁
        CellStyle border_unlocked_style = workbook.createCellStyle();
        border_unlocked_style.cloneStyleFrom(border_locked_style);
        border_unlocked_style.setLocked(false);

        // 灰色背景 + 边框 + 锁
        CellStyle grey_bg = workbook.createCellStyle();
        grey_bg.cloneStyleFrom(border_locked_style);
        grey_bg.setAlignment(HorizontalAlignment.CENTER);//左右居中
        grey_bg.setVerticalAlignment(VerticalAlignment.CENTER);//上下居中
        grey_bg.setFillForegroundColor(HSSFColor.HSSFColorPredefined.GREY_25_PERCENT.getIndex());//设置背景色
        grey_bg.setFillPattern(FillPatternType.SOLID_FOREGROUND);//填充模式

        // 日期样式 + 不锁
        CellStyle date_style = workbook.createCellStyle();
        date_style.cloneStyleFrom(border_unlocked_style);
        date_style.setLocked(false);

        // 文本框样式 + 不锁
        CellStyle text_style = workbook.createCellStyle();
        text_style.cloneStyleFrom(border_unlocked_style);
        text_style.setLocked(false);
        text_style.setDataFormat(workbook.createDataFormat().getFormat("@"));

        // 选项样式 + 不锁
        CellStyle down_style = workbook.createCellStyle();
        down_style.cloneStyleFrom(border_unlocked_style);
        down_style.setVerticalAlignment(VerticalAlignment.CENTER);
        down_style.setAlignment(HorizontalAlignment.CENTER);

        CellStyle option_style = workbook.createCellStyle();
        option_style.setVerticalAlignment(VerticalAlignment.CENTER);
        option_style.setAlignment(HorizontalAlignment.LEFT);
        option_style.setWrapText(true);
        option_style.setLocked(true);

        // 边框+居中+锁
        CellStyle border_center_style = workbook.createCellStyle();
        border_center_style.cloneStyleFrom(border_locked_style);
        border_center_style.setVerticalAlignment(VerticalAlignment.CENTER);
        border_center_style.setAlignment(HorizontalAlignment.CENTER);
        border_center_style.setLocked(true);

        CellStyle quest_border_bottom = workbook.createCellStyle();
        quest_border_bottom.setBorderBottom(BorderStyle.THIN);
        // 创建excel数据校验类
        DataValidationHelper helper = sheet.getDataValidationHelper();
        // step 1.基本信息
        Row row_0 = sheet.createRow(0);
        Cell cell1 = row_0.createCell(0);
        cell1.setCellValue("基本信息");

        // tips 順序不能调换，先合并在设置样式
        ExcelUtils.setRegionBorder(sheet, new CellRangeAddress(0, 0, 0, gaugeExcelMaxCol - 1), BorderStyle.THIN);
        cell1.setCellStyle(grey_bg);

        // step 2.基本信息填空表格
        // 查询量表的档案模板
        List<PatientItem> patientItems = data.getPatientModuleList().isEmpty() ?
                Arrays.stream(PatientModule.values()).map(PatientModule::getItem).collect(Collectors.toList()):
                data.getPatientModuleList().stream().map(PatientModule::getItem).collect(Collectors.toList());
        for (int i = 0; i < patientItems.size(); i++) {
            // 档案模板行
            int realRow = 1 + i / (gaugeExcelMaxCol / 2);
            // 档案模板 label 所在列
            int labelCol = (i % (gaugeExcelMaxCol / 2)) * 2;
            // 档案模板 输入框 所在列
            int inputCol = labelCol + 1;
            // 模板
            PatientItem archiveModule = patientItems.get(i);
            // 模板行
            Row archiveInfoRow;
            if (sheet.getRow(realRow) == null) {
                archiveInfoRow = sheet.createRow(realRow);
                ExcelUtils.setStyle(sheet, realRow, realRow, 0, gaugeExcelMaxCol - 1, border_locked_style);
            } else {
                archiveInfoRow = sheet.getRow(realRow);
            }
            // 创建模板 label，并设置值
            Cell labelCell = archiveInfoRow.getCell(labelCol);
            labelCell.setCellValue(archiveModule.getLabel());
            labelCell.setCellStyle(border_locked_style);
            // 创建模板 输入框
            if ("select".equals(archiveModule.getType()) && StringUtils.isNotBlank(archiveModule.getDictCode())) {
                // 数据字典下拉框
                String[] dropDownData = dictDataService.selectDictDataByType(archiveModule.getDictCode())
                        .stream()
                        .map(Option::getLabel)
                        .toArray(String[]::new);
                ExcelUtils.setRadioValidation(sheet, helper, dropDownData, realRow, realRow, inputCol, inputCol);
                sheet.getRow(realRow).getCell(inputCol).setCellStyle(border_unlocked_style);
            } else if ("date".equals(archiveModule.getType())) {
                // 日期格式
                DataFormat dataFormat = workbook.createDataFormat();
                String format = StringUtils.defaultIfEmpty(archiveModule.getFormat(), "yyyy-MM-dd");
                date_style.setDataFormat(dataFormat.getFormat(format));
                sheet.getRow(realRow).getCell(inputCol).setCellStyle(date_style);
                ExcelUtils.setDateValidation(sheet,
                        helper,
                        format,
                        new CellRangeAddressList(realRow, realRow, inputCol, inputCol));
            } else {
                // 普通文本
                archiveInfoRow.createCell(inputCol, CellType.STRING).setCellStyle(text_style);
            }
        }
        // 创建量表信息行，并设置值和样式
        int gaugeInfoRowNum = sheet.getLastRowNum() + 1;
        Row gaugeInfoRow = sheet.createRow(gaugeInfoRowNum);
        Cell gaugeInfoRow_cell = gaugeInfoRow.createCell(0);
        gaugeInfoRow_cell.setCellValue("量表信息");
        // tips 順序不能调换，先合并在设置样式
        ExcelUtils.setRegionBorder(sheet, new CellRangeAddress(gaugeInfoRowNum, gaugeInfoRowNum, 0, gaugeExcelMaxCol - 1), BorderStyle.THIN);
        gaugeInfoRow_cell.setCellStyle(grey_bg);

        // step 3.创建量表名称行，并设置值和样式
        int gaugeNameRow = gaugeInfoRowNum + 1;
        Row row_2 = sheet.createRow(gaugeNameRow);
        Cell row_2_cell0 = row_2.createCell(0);
        row_2_cell0.setCellValue(data.getTitle());
        // tips 先合并，在设置样式
        ExcelUtils.setRegionBorder(sheet, new CellRangeAddress(gaugeNameRow, gaugeNameRow, 0, gaugeExcelMaxCol - 2), BorderStyle.THIN);
        row_2_cell0.setCellStyle(grey_bg);

        // step 4.结果
        Cell row_2_cell1 = row_2.createCell(gaugeExcelMaxCol - 1);
        row_2_cell1.setCellValue("答案");
        row_2_cell1.setCellStyle(grey_bg);

        // step 5.生成题目和选项下拉框或填空框

        // 初始化题目字体样式
        XSSFFont questionFont = workbook.createFont();
        questionFont.setBold(true);
        // 计算题目开始行
        int questionStartRow = sheet.getLastRowNum() + 1;

        int questionSize = data.getQuestions().size();
        // 遍历量表题目
        for (int i = 0; i < questionSize; i++) {
            // 获取题目
            final TblGaugeQuestion question = data.getQuestions().get(i);
            if (i > 0) {
                questionStartRow += data.getQuestions().get(i - 1).getOptions().size() + 1;
            }
            // 创建题目行
            Row tmRow = sheet.createRow(questionStartRow);
            // 创建题目编号单元格，并设置值和样式
            Cell questionNumCell = tmRow.createCell(0);
            questionNumCell.setCellValue(question.getQutSort());
            questionNumCell.setCellStyle(border_center_style);
            // 创建题目单元格
            Cell questionCell = tmRow.createCell(1);
            // tips 判断题目内容是否为图片
            if (question.getQutContent().startsWith(Constants.RESOURCE_PREFIX)) {
                try {
                    /**
                     * dx1：图片距离单元格左边偏移量 ,dy1：图片距离单元格上边偏移量 ,dx2：图片距离单元格右边偏移量 ,dy2：图片距离单元格下边偏移量  这里设置为1为不覆盖边框
                     * col1：起始列 、row1：起始行 、col2：截止列 、row2：截止行 (下标 0 开始)
                     */
                    XSSFClientAnchor anchor = new XSSFClientAnchor(Units.pixelToEMU(1), Units.pixelToEMU(1), Units.pixelToEMU(1), Units.pixelToEMU(1),
                            1, questionStartRow, gaugeExcelMaxCol - 2, questionStartRow);
                    // 插入图片,宽度最大为合并后列宽和，高度自适应
                    ExcelUtils.insertImageToCell(sheet, anchor,
                            ImageUtils.readFile(question.getQutContent()),
                            XSSFWorkbook.PICTURE_TYPE_PNG
                    );
                } catch (IOException e) {
                    questionCell.setCellValue("图片加载失败");
                    e.printStackTrace();
                }
            } else {
                // 添加题目内容
                XSSFRichTextString xssfRichTextString = new XSSFRichTextString(question.getQutContent());
                if (StringUtils.isNotBlank(question.getPrompt())) {
                    xssfRichTextString.append("\r\n" + question.getPrompt());
                }
                questionCell.setCellValue(xssfRichTextString);
            }
            // 合并题目单元格列、并设置边框
            ExcelUtils.setRegionBorder(sheet, new CellRangeAddress(questionStartRow, questionStartRow, 1, gaugeExcelMaxCol - 2),
                    BorderStyle.THIN, BorderStyle.THIN, BorderStyle.NONE, BorderStyle.THIN);
            questionCell.setCellStyle(option_style);
            for (int j = 1; j < question.getOptions().size() + 1; j++) {
                // 获取选项
                final TblGaugeOption option = question.getOptions().get(j - 1);
                // 创建下拉框单元格
                Row optionRow = sheet.createRow(questionStartRow + j);
                Cell answerCell = optionRow.createCell(gaugeExcelMaxCol - 1);
                if (question.getType() == QuestionType.radio) {
                    if (j == 1) {
                        // 设置选项下拉框
                        ExcelUtils.setRadioValidation(
                                sheet,
                                helper,
                                question.getOptions().stream().map(TblGaugeOption::getOptSymbol).toArray(String[]::new),
                                questionStartRow,
                                questionStartRow,
                                gaugeExcelMaxCol - 1,
                                gaugeExcelMaxCol - 1);
                        // 设置下拉框单元格样式
                        answerCell.setCellStyle(down_style);
                    }
                    Cell optionCell = optionRow.createCell(1);
                    // 合并选项单元格、设置边框
                    ExcelUtils.setRegionBorder(sheet, new CellRangeAddress(questionStartRow + j, questionStartRow + j, 1, 6),
                            BorderStyle.NONE);
                    if (option.getOptContent().startsWith(Constants.RESOURCE_PREFIX)) {
                        try {
                            /**
                             * dx1：图片距离单元格左边偏移量 ,dy1：图片距离单元格上边偏移量 ,dx2：图片距离单元格右边偏移量 ,dy2：图片距离单元格下边偏移量  这里设置为1为不覆盖边框
                             * col1：起始列 、row1：起始行 、col2：截止列 、row2：截止行
                             */
//                            optionRow.setHeightInPoints(50.0f);
                            optionCell.setCellValue(option.getOptSymbol() + ".");
                            XSSFClientAnchor anchor = new XSSFClientAnchor(Units.pixelToEMU(24), Units.pixelToEMU(1), Units.pixelToEMU(1), Units.pixelToEMU(1),
                                    1, j + questionStartRow, 2, j + questionStartRow + 1);
                            ExcelUtils.insertImageToCell(sheet, anchor,
                                    ImageUtils.readFile(option.getOptContent()),
                                    XSSFWorkbook.PICTURE_TYPE_PNG);
                        } catch (IOException e) {
                            optionCell.setCellValue(option.getOptSymbol() + ". 图片加载失败");
                            e.printStackTrace();
                        }
                    } else {
                        optionCell.setCellValue(String.join(".", option.getOptSymbol(), option.getOptContent()));
                    }
                    optionCell.setCellStyle(option_style);
                } else if (question.getType() == QuestionType.number) {
                    // 数据校验，只能输入数值
                    ExcelUtils.setNumberValidation(sheet, helper, new CellRangeAddressList(questionStartRow, questionStartRow, gaugeExcelMaxCol - 1, gaugeExcelMaxCol - 1));
                } else {
                    // 设置文本框单元格样式
                    answerCell.setCellStyle(text_style);
                }
            }
            // 合并题目编号单元格列、并设置边框
            ExcelUtils.setRegionBorder(sheet, new CellRangeAddress(questionStartRow, questionStartRow + question.getOptions().size(), 0, 0), BorderStyle.THIN);
            // 每一题最下面边框
            ExcelUtils.setStyle(sheet, questionStartRow + question.getOptions().size(), questionStartRow + question.getOptions().size(), 1, gaugeExcelMaxCol - 2, quest_border_bottom);
            // 设置下拉框样式
            ExcelUtils.setStyle(sheet, questionStartRow, questionStartRow + question.getOptions().size(), gaugeExcelMaxCol - 1, gaugeExcelMaxCol - 1, down_style);
            // 合并选项下拉框单元格列、并设置边框
            ExcelUtils.setRegionBorder(sheet, new CellRangeAddress(questionStartRow, questionStartRow + question.getOptions().size(), gaugeExcelMaxCol - 1, gaugeExcelMaxCol - 1), BorderStyle.THIN);

            if (question.getType() == QuestionType.number) {
                // 数据校验，只能输入数值
                ExcelUtils.setNumberValidation(sheet, helper, new CellRangeAddressList(questionStartRow, questionStartRow, gaugeExcelMaxCol - 1, gaugeExcelMaxCol - 1));
            }
        }
        //设置自动换行
        sheet.setAutobreaks(true);
        return workbook;
    }

}
